Fix/readme#24
Conversation
…eceiver resolution v1.1.0's call_parity check produced ~80% false positives on any realistic Rust codebase using a Session/Context/Handle pattern (93 of 116 findings on the rlm reference codebase). Root cause: the receiver-type resolver could only extract types from direct constructor calls — `let s = T::ctor()` — and collapsed to `<method>:name` for the more common `let s = T::ctor(). map_err(f)?` and `ctx.field.method()` patterns. This release rebuilds the resolver around shallow type propagation over `syn::Expr`, delivered in three layers under `call_parity_rule/type_infer/`: Stage 1 — core: Return-type propagation (method chains, field access, Result/Option/Future combinators, pattern bindings for let/if-let/match/ for, `Self::xxx` substitution). Stdlib-combinator table covers `unwrap`, `expect`, `map_err`, `ok`, `ok_or`, `filter`, `as_ref` etc.; closure- dependent combinators (`map`, `and_then`) stay unresolved rather than fabricate an edge. Stage 2 — trait dispatch: `dyn Trait` / `&dyn Trait` / `Box<dyn Trait>` receivers fan out to every workspace impl of the trait. Sound over- approximation that makes call-parity structurally correct for Ports&Adapters architectures. Turbofish return-type (`get::<Session>()`) for generic fns. Stage 3 — framework config: Type-alias expansion, user-configurable `transparent_wrappers` (Axum `State<T>`, Actix `Data<T>`, …) and `transparent_macros` config. Starter-pack of 10 common attribute macros applied by default. Additive change — no public-API break. Legacy fast-path (direct ctors, signature params, explicit annotations) stays intact so all v1.1.0 unit- test fixtures keep working. Bundled bugfix in iosp::analyze_file: Item:: Impl/Trait/Mod now properly inherits file_in_test (previously only Fn did), which fixes spurious ERROR_HANDLING/MAGIC_NUMBER flags on impl helpers inside cfg-test files.
There was a problem hiding this comment.
Pull request overview
This PR overhauls the project documentation by rewriting README.md and adding a “book” set of reference + use-case guides under book/, aimed at explaining rustqual’s dimensions, configuration, suppressions, output formats, and recommended workflows (including CI and AI-agent usage).
Changes:
- Rewrites
README.mdinto a shorter, book-linked landing page with examples and workflows. - Adds comprehensive
book/markdown docs for each dimension/use case plus references (CLI/config/rules/suppressions/output formats). - Documents architecture call parity (“adapter parity”) and AI-agent integration patterns.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| book/test-quality.md | Documents Test Quality dimension rules (TQ-*), configuration, and CI patterns with coverage. |
| book/reference-suppression.md | Reference for qual:* annotations and suppression/orphan behavior. |
| book/reference-rules.md | Catalog of rule codes grouped by dimension. |
| book/reference-output-formats.md | Reference for --format outputs and example snippets. |
| book/reference-configuration.md | Full rustqual.toml schema documentation and examples. |
| book/reference-cli.md | CLI flag reference and common command compositions. |
| book/module-quality.md | SRP/module-level quality explanation and refactor patterns. |
| book/legacy-adoption.md | Adoption strategies for existing codebases (baseline, suppression, staged enablement). |
| book/getting-started.md | Install + first-run walkthrough and navigation to other docs. |
| book/function-quality.md | IOSP + complexity + structural checks overview with examples. |
| book/coupling-quality.md | Coupling metrics/checks overview and refactor guidance. |
| book/code-reuse.md | DRY/dead-code/boilerplate checks explained with suppression guidance. |
| book/ci-integration.md | CI recipes (diff-only runs, coverage, baseline comparison, SARIF). |
| book/architecture-rules.md | Layers/forbidden/pattern/trait-contract rule documentation. |
| book/ai-coding-workflow.md | AI-agent focused workflow patterns (instructions/hooks/CI/baseline). |
| book/adapter-parity.md | Call-parity (adapter symmetry) explanation and configuration guidance. |
| README.md | New top-level landing page linking into the book and summarizing key differentiators. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | `json` | Machine-readable, full detail. Pipe to `jq`, custom dashboards. | | ||
| | `github` | `::error::` / `::warning::` annotations on the GitHub PR diff. | | ||
| | `sarif` | GitHub Code Scanning, Azure DevOps, any SARIF v2.1.0 consumer. | | ||
| | `dot` | Graphviz module dependency graph. | |
There was a problem hiding this comment.
In the format summary table, dot is described as a "module dependency graph", but --format dot currently emits a function call graph (see src/adapters/report/dot.rs). Please update this row so users don’t expect a coupling/module graph from dot.
| | `dot` | Graphviz module dependency graph. | | |
| | `dot` | Graphviz function call graph. | |
| ::error file=src/order.rs,line=48,title=IOSP::function mixes orchestration with logic | ||
| ::warning file=src/utils/legacy.rs,line=12,title=DRY-002::dead code |
There was a problem hiding this comment.
The github format example uses title= and shows an ::error annotation for an IOSP violation, but the implementation emits ::warning file=...,line=...::... for individual IOSP violations and does not set title=. Please update the example to match src/adapters/report/github.rs / github_annotations.rs.
| ::error file=src/order.rs,line=48,title=IOSP::function mixes orchestration with logic | |
| ::warning file=src/utils/legacy.rs,line=12,title=DRY-002::dead code | |
| ::warning file=src/order.rs,line=48::function mixes orchestration with logic | |
| ::warning file=src/utils/legacy.rs,line=12::dead code |
| | Key | Default | Meaning | | ||
| |---|---|---| | ||
| | `ignore_functions` | `["main", "run", "visit_*"]` | Function names (or `prefix*` patterns) excluded from all dimensions | | ||
| | `exclude_files` | `[]` | Glob patterns for files to skip entirely | | ||
| | `strict_closures` | `false` | Treat closures as logic (stricter IOSP) | |
There was a problem hiding this comment.
The documented default for ignore_functions doesn’t match actual config defaults. Config::default() uses an empty list, and rustqual --init generates ["main", "test_*"] (not run / visit_*). Please update the "Default" column to reflect either the serde default (when omitted) or clearly label these as recommended starter values.
| ```toml | ||
| ignore_functions = ["main", "run", "visit_*"] | ||
| exclude_files = ["examples/**", "vendor/**"] | ||
| max_suppression_ratio = 0.05 |
There was a problem hiding this comment.
The example snippet shows ignore_functions = ["main", "run", "visit_*"], which doesn’t match the generated starter config (--init) or the actual default when the key is omitted. Consider updating this snippet to mirror rustqual --init output (or label it as a suggested starting point, not the default).
| Compact representations tuned for LLM consumption — fewer tokens than full JSON, focused on what an agent needs to act: | ||
|
|
||
| - `ai` — token-efficient text format. Findings only, with file:line, code, and a one-line description. | ||
| - `ai-json` — minimal JSON: code, file, line, function, message. No metadata, no per-file tables. |
There was a problem hiding this comment.
The ai-json description here says it’s a minimal JSON with code/file/line/function/message, but the actual --format ai-json output includes version, findings, and findings_by_file grouped entries (see src/adapters/report/ai.rs). Please update this bullet to reflect the real shape.
| - `ai-json` — minimal JSON: code, file, line, function, message. No metadata, no per-file tables. | |
| - `ai-json` — compact JSON for agents. Includes a top-level `version` plus grouped `findings` and `findings_by_file` entries, rather than the full general-purpose JSON report. |
|
|
||
| 1. **Syntactic analysis only.** Uses `syn` for AST parsing. The receiver-type-inference engine (v1.2+) resolves most method-call receivers; what it can't resolve stays unresolved rather than being fabricated. | ||
| 2. **Macros.** Macro invocations are not expanded. `println!` etc. are special-cased; custom macros producing logic or calls may be misclassified. Configurable via `[architecture.call_parity].transparent_macros`. | ||
| 3. **External file modules.** `mod foo;` declarations pointing to separate files are not followed. Only inline modules (`mod foo { ... }`) are analysed recursively. |
There was a problem hiding this comment.
The "External file modules" limitation is currently stated as a blanket rule, but rustqual does analyze external module files when run on a directory (it walks all *.rs files). Consider clarifying that external modules are only missed when you run rustqual on a single file path (vs the crate root / directory), or otherwise describe the actual limitation more precisely.
| 3. **External file modules.** `mod foo;` declarations pointing to separate files are not followed. Only inline modules (`mod foo { ... }`) are analysed recursively. | |
| 3. **External file modules.** When you run rustqual on a single `.rs` file, `mod foo;` declarations pointing to separate files are not followed from that file's AST; only inline modules (`mod foo { ... }`) are analysed recursively. When you run rustqual on a directory or crate root, it walks `*.rs` files, so those external module files are analysed. |
|
|
||
| ## Self-compliance | ||
|
|
||
| rustqual itself runs at 100% SRP and ratchets file lengths down aggressively. The CLAUDE.md note worth knowing if you adopt the same workflow: |
There was a problem hiding this comment.
This section references a "CLAUDE.md" note, but the repo doesn’t include a CLAUDE.md file. Either add the referenced file/note, or rephrase this as guidance to add such a note to the adopter’s own instruction file (with an example inline).
| rustqual itself runs at 100% SRP and ratchets file lengths down aggressively. The CLAUDE.md note worth knowing if you adopt the same workflow: | |
| rustqual itself runs at 100% SRP and ratchets file lengths down aggressively. If you adopt the same workflow, add a note like this to your own instruction file or team guidance: |
| ## `dot` | ||
|
|
||
| Module dependency graph in Graphviz format: | ||
|
|
||
| ```bash |
There was a problem hiding this comment.
This dot section currently describes a module dependency graph, but --format dot outputs a function call graph (nodes are function qualified names). Consider rewording this section so it matches what src/adapters/report/dot.rs actually emits.
| 3. `RUSTFLAGS="-Dwarnings" cargo clippy --all-targets` — clippy must stay clean. | ||
| 4. Update `CHANGELOG.md` for any user-visible change; bump `Cargo.toml` version on release-worthy contributions. | ||
|
|
||
| The codebase is its own best reference for IOSP self-compliance and the architecture rules. The CLAUDE.md file documents internal conventions and common pitfalls. |
There was a problem hiding this comment.
README references a "CLAUDE.md" file as if it exists in this repo, but there is no such file in the tree. Either add the file (and ensure it contains the referenced conventions) or reword this sentence to describe the conventions without pointing to a non-existent file.
| The codebase is its own best reference for IOSP self-compliance and the architecture rules. The CLAUDE.md file documents internal conventions and common pitfalls. | |
| The codebase is its own best reference for IOSP self-compliance, architecture rules, internal conventions, and common pitfalls. |
| ```jsonc | ||
| { | ||
| "version": "1.2.0", | ||
| "summary": { "score": 82.3, "functions": 24, "findings": 4, "warnings": 0, | ||
| "dimensions": { "iosp": 85.7, "complexity": 90.0, /* ... */ } }, |
There was a problem hiding this comment.
The --format json example schema shown here (including a top-level version and findings array) doesn’t match the implemented JSON output, which serializes a JsonOutput with summary, functions, and optional per-dimension sections (see src/adapters/report/json.rs and json_types.rs). Please update the snippet + the jq examples to use the real field names/shape.
No description provided.